package com.koc.robot.font;

import java.nio.ByteBuffer;

import com.koc.robot.freetype.Bitmap;
import com.koc.robot.freetype.Face;
import com.koc.robot.freetype.FreeType;
import com.koc.robot.freetype.GlyphSlot;

class GlyphMetrics
{
	public int height;
	public int width;
	public int advance;
	public int bearingX;
	public int bearingY;
	public int spacing;
}

public class GlyphData
{
	private byte[] data  = null;
	private int glyph;
	GlyphMetrics metrics = new GlyphMetrics();
	
	public static GlyphData getGlyphData(int glyph, Face face) throws Exception
	{
		GlyphMetrics glyphMetrics = new GlyphMetrics();
		
		// Initialize
		if (!FreeType.loadGlyph(face, FreeType.getCharIndex(face, glyph), FreeType.FT_LOAD_DEFAULT))
			throw new Exception("TrueTypeFont Loading vm->error: FreeType.loadGlyph failed\n");
		if (!FreeType.renderGlyph(face.getGlyph(), FreeType.FT_RENDER_MODE_NORMAL))
			throw new Exception("TrueTypeFont Loading vm->error: renderGlyph failed\n");
		
		GlyphSlot slot = face.getGlyph();
		Bitmap bitmap = slot.getBitmap();
		
		// Get metrics
		glyphMetrics.bearingX = slot.getMetrics().getHoriBearingX() >> 6;
		glyphMetrics.bearingY = slot.getMetrics().getHoriBearingY() >> 6;
		glyphMetrics.height = bitmap.getRows();
		glyphMetrics.width = bitmap.getWidth();
		glyphMetrics.advance = slot.getMetrics().getHoriAdvance() >> 6;
		
		GlyphData glyphData = new GlyphData(glyph, glyphMetrics);
		
		{
			int size = bitmap.getRows() * bitmap.getWidth();
			byte[] dst = glyphData.getData();
			
			// bitmap.buffer contains only luminosity. We copy that single value to our
			// luminosity-alpha format.
			for (int i = 0; i < size; i++)
			{
				dst[2 * i] = (byte) 255;
				dst[2 * i + 1] = bitmap.getBuffer().get(i);
			}
		}
		
		// Return data
		return glyphData;
	}
	
	public GlyphData(int glyph, GlyphMetrics glyphMetrics)
	{
		this.glyph = glyph;
		this.metrics = glyphMetrics;
		
		if (glyphMetrics.width != 0 && glyphMetrics.height != 0)
		{
			data = new byte[metrics.width * metrics.height * 2];
		}
	}
	
	public byte[] getData() 
	{
		return data;
	}
	
	public int getSize()
	{
		return getWidth() * getHeight() * 2;
	}
	
	public int getHeight()
	{
		return metrics.height;
	}
	
	public int getWidth()
	{
		return metrics.width;
	}
	
	public int getAdvance()
	{
		return metrics.advance;
	}
	
	public int getBearingX()
	{
		return metrics.bearingX;
	}
	
	public int getBearingY()
	{
		return metrics.bearingY;
	}
	
	public int getMinX() 
	{
		return getBearingX();
	}
	
	public int getMinY()
	{
		return getHeight() - getBearingY();
	}
	
	public int getMaxX()
	{
		return getBearingX() + getWidth();
	}
	
	public int getMaxY()
	{
		return this.getBearingY();
	}
}
